在这张效果图中涉及三个发光效果:文字、图形和位图。
从最后一张美女位图所形成的发光效果中可以看到,与 setShadowLayer() 函数一样,发光效果也只会影响边缘部分图像,内部图像是不受影响的。
从第三幅图像(红绿各一半的位图)中可以看到:发光效果是无法指定发光颜色的,采用边缘部分的颜色取样来进行模糊发光。所以边缘是什么颜色,发出的光也就是什么颜色的。
所以初步我们对发光效果有如下结论:
- 与 setShadowLayer() 函数一样,发光效果使用的也是高斯模糊算法,并且只会影响边缘部分图像,内部图像是不受影响的。
- 发光效果是无法指定发光颜色的,采用边缘部分的颜色取样来进行模糊发光。所以边缘是什么颜色,发出的光也就是什么颜色的。
7.3.1 概述
|
|
setMaskFilter() 函数中的 MaskFilter 也是没有具体实现的,是通过派生子类来实现具体的不同功能的。MaskFilter 有两个派生类:BlurMaskFilter 和 EmbossMaskFilter。其中,BlurMaskFilter 就能够实现发光效果;而 EmbossMaskFilter 则可以用于实现浮雕效果,用处很少,这里就不再讲解了。另一点需要注意的是,setMaskFilter() 函数是不支持硬件加速的,必须关闭硬件加速才可以。
BlurMaskFilter 的构造函数如下:
- float radius:用来定义模糊半径,同样是高斯模糊算法。
- Blur style:发光样式,有内 Blur.INNER(内发光)、Blur.SOLID(外发光)、Blur.NORMAL(内外发光)、Blur.OUTER(仅发光部分可见)。
上面效果图的示例代码如下:
BlurStyle 发光效果图
示例代码:
其中,Blur.OUTER 比较特殊,在这种模式下仅显示发光效果,会把原图像中除发光部分外的其他部分全部变为透明。
7.3.2 给图片添加纯色阴影
大家是否可以看出来发光效果与 setShadowLayer() 函数所生成的阴影之间有什么联系?
先来分析一下 setShadowLayer() 函数的阴影形成过程(假定阴影画笔是灰色)。对于文字和图形,它首先产生一个跟原型一样的灰色副本。然后对这个灰色副本应用 BlurMaskFilter,使其内外发光;这样就形成了所谓的阴影,当然最后再偏移一段距离。
所以,我们要给图片添加灰色阴影效果,就可以仿照这个过程:先绘制一幅跟图片一样大小的灰色图像,然后给这个灰色图形应用 BlurMaskFilter 使其内外发光,最后偏移原图形一段距离绘制阴影。
这里涉及到三个点:
- 绘制一幅跟图片一样大小的灰色图像。
- 对灰色图像应用 BlurMaskFilter 使其内外发光。
- 偏移原图形一段距离绘制阴影。
1. 抽取灰色图像
首先来看怎么能绘出一个指定位图所对应的灰色图像。我们知道 canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) 中的画笔颜色对画出来的位图是没有任何影响的,所以,如果我们需要画一张对应的灰色图像,就需要新建一张一样大小的空白图,而且新图片的透明度要与原图片保持一致。这样一来,如何从原图片中抽出 Alpha 值成为关键。即我们只需要创建一个与原图片一样大小且 Alpha 相同的图片即可。
其实,Bitmap 中已经存在抽取出只具有 Alpha 值图片的函数:
这个函数的功能是:新建一张空白图片,该图片具有与原图片一样的 Alpha 值,把这个新建的 Bitmap 作为结果返回。这个空白图片中每个像素都具有与原图片一样的 Alpha 值,而且具体的颜色是在使用canvas.drawBitmap() 函数绘制时由传入的画笔颜色指定的。
总结:extractAlpha() 会新建一幅仅具有 Alpha 值的空白图像,而且这张图像的颜色是在使用 canvas.drawBitmap() 函数绘制时传入的画笔颜色指定的。
下面拿一张图片来做实验,这张 PNG 图片中,只有一只小狗,其余地方都是透明色。
下面分别利用 extractAlpha() 函数画出该图片所对应的灰色和黑色阴影,效果图如下所示。
示例代码:
2. 绘制阴影
在上面灰色纯色图像的基础上,将此灰色图像使用 BlurMaskFilter 使其内外发光。然后再在灰色模糊阴影的基础上画上原图像,就形成了模糊阴影。代码如下:
效果如下图所示。
7.3.3 封装控件
将它封装成一个控件,具有如下功能:
- 让用户定义图片内容。
- 让用户定义偏移距离。
- 让用户定义阴影颜色和阴影模糊程度。
- 可以使用 wrap_content 属性自适应大小。
下面程序经过多次测试,效果并不完美,待完善。
res/values/xshadow.xml
src/…/XShadowImageView.java
使用: